import dayjs from 'dayjs'
import { ExcelUtil } from '@/utils'
import { UAParser } from 'ua-parser-js'
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { LOGININFO_EXCEL_COLUMNS } from './log.excel'
import { RedisService } from '@/shared/redis.service'
import { SharedService } from '@/shared/shared.service'
import { FindOptionsWhere, Like, Repository } from 'typeorm'
import { CacheKey, LogininfoEntity, TimeFormat, TimeUnit } from '@/common'

@Injectable()
export class LogService {
  constructor(
    private redisService: RedisService,
    private readonly sharedService: SharedService,
    @InjectRepository(LogininfoEntity) private readonly logininforRepository: Repository<LogininfoEntity>,
  ) {}

  /** 新增登录日志 */
  public async createLoginLog(request: ExpressRequest, message: string, tokenKey?: string) {
    const { username } = request.body
    const parser = new UAParser(request.headers['user-agent']) //获取用户电脑信息
    const browserInfo = parser.getBrowser()
    const osInfo = parser.getOS()
    // 创建日志实体
    const loginLog = new LogininfoEntity()
    loginLog.username = username
    loginLog.browser = `${browserInfo.name} ${browserInfo.version!.split('.')[0]}`
    loginLog.os = `${osInfo.name!} ${osInfo.version || 'Unknown'}`
    loginLog.ip = this.sharedService.getRequestIp(request)
    loginLog.message = message
    loginLog.status = tokenKey ? 1 : 0 // 1 成功 0 失败
    loginLog.address = await this.sharedService.getLocationByIP(loginLog.ip)
    loginLog.loginTime = dayjs().format(TimeFormat.DATETIME_DASH)
    // 如果登录成功，就记录这个登录信息，方便在线用户查询
    if (tokenKey) {
      const { ip, address, username, loginTime, browser, os } = loginLog
      const userId = tokenKey.replace(`${CacheKey.ADMIN_USER_TOKEN}:`, '')
      const record = { userId, ip, address, username, loginTime, browser, os }
      await this.redisService.setEx(`${CacheKey.ADMIN_USER_ONLINE}:${userId}`, JSON.stringify(record), TimeUnit.HALF_HOUR)
    }
    await this.logininforRepository.save(loginLog)
    return '登录日志记录成功'
  }

  /** 分页查询登录日志 */
  public async findLogininfoList(queryParams: TableQueryParams<LogininfoEntity>) {
    const { take = 10, skip = 0, username = '', address = '', ip, status } = queryParams
    const where: FindOptionsWhere<LogininfoEntity> = {}
    if (ip) where.ip = Like(`%${ip}%`)
    if (username) where.username = Like(`%${username}%`)
    if (address) where.address = Like(`%${address}%`)
    if (status) where.status = +status
    const queryBuilder = this.logininforRepository.createQueryBuilder('logininfor')
    queryBuilder.where(where)
    queryBuilder.orderBy('logininfor.loginTime', 'DESC') // 排序
    queryBuilder.skip(skip).take(take) // 分页
    const [records, total] = await queryBuilder.getManyAndCount() //  一次性获取数据和总数
    return { total, records }
  }

  /** 清空登录日志 */
  public async clearLogininfo() {
    // await this.logininforRepository.createQueryBuilder('logininfo').delete().execute()
    await this.logininforRepository.clear()
    return '登录日志清空成功'
  }

  /** 删除登录日志 */
  public async deleteLogininfo(ids: string[]) {
    await this.logininforRepository.delete(ids)
    return '删除成功'
  }

  /** 导出登录日志 */
  public async exportLogininfoExcel() {
    const records = await this.logininforRepository.find()
    const formattedRecords = records.map((record) => ({ ...record, status: record.status === 1 ? '成功' : '失败' }))
    return ExcelUtil.export(formattedRecords, { columns: LOGININFO_EXCEL_COLUMNS })
  }
}
